// 版权归 Epic Games, Inc. 所有。保留所有权利。

#include "LyraTabListWidgetBase.h"

#include "CommonAnimatedSwitcher.h"
#include "CommonButtonBase.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraTabListWidgetBase)

/**
 * 原生初始化实现
 */
void ULyraTabListWidgetBase::NativeOnInitialized()
{
	Super::NativeOnInitialized(); // 调用父类初始化
}

/**
 * 原生构造实现
 */
void ULyraTabListWidgetBase::NativeConstruct()
{
	Super::NativeConstruct(); // 调用父类构造

	SetupTabs(); // 设置选项卡
}

/**
 * 原生析构实现
 */
void ULyraTabListWidgetBase::NativeDestruct()
{
	// 清理所有预注册选项卡的内容控件
	for (FLyraTabDescriptor& TabInfo : PreregisteredTabInfoArray)
	{
		if (TabInfo.CreatedTabContentWidget) // 如果已创建内容控件
		{
			TabInfo.CreatedTabContentWidget->RemoveFromParent(); // 从父级移除
			TabInfo.CreatedTabContentWidget = nullptr; // 置空指针
		}
	}

	Super::NativeDestruct(); // 调用父类析构
}

/**
 * 获取预注册的选项卡信息实现
 * @param TabNameId 选项卡名称ID
 * @param OutTabInfo 输出的选项卡信息
 * @return 是否找到
 */
bool ULyraTabListWidgetBase::GetPreregisteredTabInfo(const FName TabNameId, FLyraTabDescriptor& OutTabInfo)
{
	// 查找匹配的选项卡信息
	const FLyraTabDescriptor* const FoundTabInfo = PreregisteredTabInfoArray.FindByPredicate([&](FLyraTabDescriptor& TabInfo) -> bool
	{
		return TabInfo.TabId == TabNameId; // 比较选项卡ID
	});

	if (!FoundTabInfo) // 未找到
	{
		return false;
	}

	OutTabInfo = *FoundTabInfo; // 输出选项卡信息
	return true; // 返回成功
}

/**
 * 设置选项卡隐藏状态实现
 * @param TabNameId 选项卡名称ID
 * @param bHidden 是否隐藏
 */
void ULyraTabListWidgetBase::SetTabHiddenState(FName TabNameId, bool bHidden)
{
	// 遍历查找并设置隐藏状态
	for (FLyraTabDescriptor& TabInfo : PreregisteredTabInfoArray)
	{
		if (TabInfo.TabId == TabNameId) // 找到匹配的选项卡
		{
			TabInfo.bHidden = bHidden; // 设置隐藏状态
			break; // 跳出循环
		}
	}
}

/**
 * 注册动态选项卡实现
 * @param TabDescriptor 选项卡描述符
 * @return 是否成功
 */
bool ULyraTabListWidgetBase::RegisterDynamicTab(const FLyraTabDescriptor& TabDescriptor)
{
	// 如果隐藏则忽略
	if (TabDescriptor.bHidden)
	{
		return true;
	}
	
	// 添加到待处理映射
	PendingTabLabelInfoMap.Add(TabDescriptor.TabId, TabDescriptor);

	// 注册选项卡
	return RegisterTab(TabDescriptor.TabId, TabDescriptor.TabButtonType, TabDescriptor.CreatedTabContentWidget);
}

/**
 * 处理预链接切换器改变实现
 */
void ULyraTabListWidgetBase::HandlePreLinkedSwitcherChanged()
{
	// 从关联的切换器中移除所有选项卡内容控件
	for (const FLyraTabDescriptor& TabInfo : PreregisteredTabInfoArray)
	{
		// 从链接的切换器中移除选项卡内容控件，因为它正在被解除关联。
		if (TabInfo.CreatedTabContentWidget)
		{
			TabInfo.CreatedTabContentWidget->RemoveFromParent();
		}
	}

	Super::HandlePreLinkedSwitcherChanged(); // 调用父类处理
}

/**
 * 处理后链接切换器改变实现
 */
void ULyraTabListWidgetBase::HandlePostLinkedSwitcherChanged()
{
	// 如果不是设计时且控件有效，则设置选项卡
	if (!IsDesignTime() && GetCachedWidget().IsValid())
	{
		// 如果我们在设计器中或尚未构造，不要麻烦制作选项卡
		SetupTabs();
	}

	Super::HandlePostLinkedSwitcherChanged(); // 调用父类处理
}

/**
 * 处理选项卡创建实现
 * @param TabId 选项卡ID
 * @param TabButton 选项卡按钮
 */
void ULyraTabListWidgetBase::HandleTabCreation_Implementation(FName TabId, UCommonButtonBase* TabButton)
{
	FLyraTabDescriptor* TabInfoPtr = nullptr; // 选项卡信息指针
	
	FLyraTabDescriptor TabInfo;
	// 从预注册信息中查找
	if (GetPreregisteredTabInfo(TabId, TabInfo))
	{
		TabInfoPtr = &TabInfo;
	}
	else // 从待处理映射中查找
	{
		TabInfoPtr = PendingTabLabelInfoMap.Find(TabId);
	}
	
	// 如果选项卡按钮实现了接口，则设置标签信息
	if (TabButton->GetClass()->ImplementsInterface(ULyraTabButtonInterface::StaticClass()))
	{
		if (ensureMsgf(TabInfoPtr, TEXT("创建了ID为 %s 的选项卡按钮但未指定标签信息。应使用 RegisterDynamicTab 而不是 RegisterTab 来提供标签信息。"), *TabId.ToString()))
		{
			ILyraTabButtonInterface::Execute_SetTabLabelInfo(TabButton, *TabInfoPtr); // 执行设置标签信息
		}
	}

	PendingTabLabelInfoMap.Remove(TabId); // 从待处理映射中移除
}

/**
 * 检查第一个选项卡是否激活实现
 * @return 是否激活
 */
bool ULyraTabListWidgetBase::IsFirstTabActive() const
{
	// 检查第一个选项卡是否激活
	if (PreregisteredTabInfoArray.Num() > 0)
	{
		return GetActiveTab() == PreregisteredTabInfoArray[0].TabId;
	}

	return false;
}

/**
 * 检查最后一个选项卡是否激活实现
 * @return 是否激活
 */
bool ULyraTabListWidgetBase::IsLastTabActive() const
{
	// 检查最后一个选项卡是否激活
	if (PreregisteredTabInfoArray.Num() > 0)
	{
		return GetActiveTab() == PreregisteredTabInfoArray.Last().TabId;
	}

	return false;
}

/**
 * 检查选项卡是否可见实现
 * @param TabId 选项卡ID
 * @return 是否可见
 */
bool ULyraTabListWidgetBase::IsTabVisible(FName TabId)
{
	// 获取选项卡按钮并检查可见性
	if (const UCommonButtonBase* Button = GetTabButtonBaseByID(TabId))
	{
		const ESlateVisibility TabVisibility = Button->GetVisibility(); // 获取可见性
		return (TabVisibility == ESlateVisibility::Visible
			|| TabVisibility == ESlateVisibility::HitTestInvisible
			|| TabVisibility == ESlateVisibility::SelfHitTestInvisible); // 判断是否可见
	}

	return false;
}

/**
 * 获取可见选项卡数量实现
 * @return 可见选项卡数量
 */
int32 ULyraTabListWidgetBase::GetVisibleTabCount()
{
	int32 Result = 0; // 结果计数器
	const int32 TabCount = GetTabCount(); // 获取选项卡总数
	// 遍历所有选项卡统计可见数量
	for ( int32 Index = 0; Index < TabCount; Index++ )
	{
		if (IsTabVisible(GetTabIdAtIndex( Index ))) // 如果选项卡可见
		{
			Result++; // 计数器增加
		}
	}

	return Result; // 返回结果
}

/**
 * 设置选项卡实现
 */
void ULyraTabListWidgetBase::SetupTabs()
{
	// 遍历所有预注册选项卡信息
	for (FLyraTabDescriptor& TabInfo : PreregisteredTabInfoArray)
	{
		if (TabInfo.bHidden) // 如果隐藏则跳过
		{
			continue;
		}

		// 如果选项卡内容尚未创建，则创建它。
		if (!TabInfo.CreatedTabContentWidget && TabInfo.TabContentType)
		{
			TabInfo.CreatedTabContentWidget = CreateWidget<UCommonUserWidget>(GetOwningPlayer(), TabInfo.TabContentType); // 创建内容控件
			OnTabContentCreatedNative.Broadcast(TabInfo.TabId, Cast<UCommonUserWidget>(TabInfo.CreatedTabContentWidget)); // 广播原生事件
			OnTabContentCreated.Broadcast(TabInfo.TabId, Cast<UCommonUserWidget>(TabInfo.CreatedTabContentWidget)); // 广播蓝图事件
		}

		// 如果有关联的切换器，则添加内容控件
		if (UCommonAnimatedSwitcher* CurrentLinkedSwitcher = GetLinkedSwitcher())
		{
			// 将选项卡内容添加到新链接的切换器。
			if (!CurrentLinkedSwitcher->HasChild(TabInfo.CreatedTabContentWidget))
			{
				CurrentLinkedSwitcher->AddChild(TabInfo.CreatedTabContentWidget);
			}
		}

		// 如果选项卡尚未注册，则注册它。
		if (GetTabButtonBaseByID(TabInfo.TabId) == nullptr)
		{
			RegisterTab(TabInfo.TabId, TabInfo.TabButtonType, TabInfo.CreatedTabContentWidget); // 注册选项卡
		}
	}
}